package lock;

import org.junit.Test;
import sun.misc.Unsafe;

import java.lang.reflect.Field;
import java.util.PriorityQueue;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * @author: feiwang_6
 * @create: 2020/5/3 9:18
 * @description:
 */
public class TestLock {
    public static void main(String[] args) {
        int n = 1000;
        double p = 0.99;
        System.out.println((-n * Math.log(p))/(Math.log(2)*Math.log(2)));
        System.out.println(Math.log(2));
        
        System.out.println(Math.max(1, (int) Math.round((double) 10 / 2 * Math.log(2))));
    }
    
    @Test
    public void testPriorityQueue(){
        PriorityQueue<Integer> queue = new PriorityQueue<>(Integer::compareTo);
        queue.add(100);
        queue.add(20);
        queue.add(-10);
        queue.add(-1);
        System.out.println(queue);
        System.out.println(queue.poll());
        System.out.println(queue);
    }

    @Test
    public void testUnsafe() throws Exception {
        Field f = Unsafe.class.getDeclaredField("theUnsafe");
        f.setAccessible(true);
        Unsafe unsafe = (Unsafe) f.get(null);
        long startTime = System.currentTimeMillis();
        unsafe.unpark(Thread.currentThread());
        System.out.println(System.currentTimeMillis() - startTime);
    }
    
    @Test
    public void testReadWriteLock() throws InterruptedException {
        ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
        ReentrantReadWriteLock.WriteLock writeLock = lock.writeLock();
        ReentrantReadWriteLock.ReadLock readLock = lock.readLock();
        
        
        writeLock.lock();
        writeLock.unlock();
        
        
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                readLock.lock();
                try {
                    System.out.println(Thread.currentThread().getName() + " 获取readLock");
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                readLock.unlock();
                System.out.println(Thread.currentThread().getName() + " 释放readLock");
            }
        };
        
        Thread threadA = new Thread(runnable);
        Thread threadB = new Thread(runnable);
        threadA.setName("threadA");
        threadB.setName("threadB");
        threadA.start();
        Thread.sleep(100);
        threadB.start();
        
        Thread.sleep(20000);
    }
    

    @Test
    public void testLock() throws InterruptedException {
        ReentrantLock lock = new ReentrantLock();
        Thread thread = new Thread(() -> {
            try {
                lock.lockInterruptibly();
                for (int i = 1; i <= 5; i++) {
                    for (int j = 0; j < 200000; j++) {
                        Random random = new Random();
                        int number = random.nextInt(1000);
                    }
                    System.out.println(Thread.currentThread().getName() + "  " + i);
                }
                lock.unlock();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        lock.tryLock(1000, TimeUnit.SECONDS);
        
        Thread a = new Thread(thread);
        Thread b = new Thread(thread);
        a.setName("ThreadA");
        b.setName("ThreadB");
        a.start();
        Thread.sleep(10);
        b.start();
        Thread.sleep(10);
        a.interrupt();
        b.interrupt();
        System.out.println("ThreadA 设置中断......");
        System.out.println("ThreadB 设置中断......");
        Thread.sleep(10000);
    }
    
    @Test
    public void reentryLock(){
        try {
            System.out.println("qqqqqqqqqqqqqqq");
            return;
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            System.out.println("11111111111111");
        }
    }
    
    
    @Test
    public void testMethod() throws InterruptedException {
        MyServer server = new MyServer();
        Thread[] products = new Thread[20];
        Thread[] consumers = new Thread[20];
        for(int i = 0; i < products.length; i++){
            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    int count = 0;
                    while(count < 5){
                        server.set();
                        count++;
                    }
                }
            });
            products[i] = thread;
        }
        for(int i = 0; i < products.length; i++){
            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    int count = 0;
                    while(count < 5){
                        server.get();
                        count++;
                    }
                }
            });
            consumers[i] = thread;
        }
        
        for(int i = 0; i < products.length; i++){
            products[i].start();
            consumers[i].start();
        }
        
        for(int i = 0; i < products.length; i++){
            products[i].join();
            consumers[i].join();
        }
    }
    
    @Test
    public void testCallable(){
        Callable<Integer> callable = new Callable() {
            @Override
            public Object call() throws Exception {
                System.out.println("1111111111111");
                return 100;
            }
        };
        FutureTask<Integer> ft = new FutureTask<>(callable);
        Thread thread = new Thread(ft);
        thread.start();
    }
    
}
